home *** CD-ROM | disk | FTP | other *** search
- ; ============================================
- ; 4Kb Intro for the Assembly '95 competition
- ; ============================================
-
- ; Programmed by:
- ; Kim Holviala
- ; Aladininkatu 7 B 19
- ; 49400 Hamina
- ; FINLAND
-
-
- ; Asm '95 rules for the 4Kb intro:
- ; - Under 4Kb's (more than enough for anything....)
- ; - Not more than 3 minutes
- ; - Must stop with ESC
- ; - No musics
-
-
- ; To compile a .COM file (Turbo Assembler v3.0 -> ):
- ; - Make sure INTRO.ASM and VAR.MAC are present
- ; - TASM /m intro
- ; - TLINK /t intro
-
- ; To compile an .EXE with full debug data:
- ; - TASM /m /zi /ddebug intro
- ; - TLINK /v intro
-
-
- IDEAL
-
- MODEL TINY ; One segment is more than enough
-
- P386N ; The only way to do it!
-
-
- IFDEF debug ; .EXE must have an stack
-
- STACK 500h
-
- ENDIF
-
-
- INCLUDE "var.mac" ; Include macros for stack-variables
-
-
- ; Variables ===============================================
-
- VAR codesegment, WORD ; Current codesegment
- VAR vgasegment, WORD, 0A000h ; VGA memory
- VAR virtualscr, WORD ; Segment of the virtual screen
- VAR firestartscr, WORD ; Needed for the fire-effect
-
- VAR temp, WORD ; Temporal storage
- VAR count, BYTE ; Counts anything
- VAR power_meter, WORD ; Calculates the speed of the computer
- VAR timer, WORD, 0 ; 60 ticks/sec clock
-
- VAR dot_curr_char, WORD ; Current charptr for the dot-scroll
- VAR dot_horiz_place,BYTE, 0 ; Next vertical column to be printed
-
- VAR sin_start_char, WORD ; Start charptr for the sinus-scroll
- VAR sin_curr_char, WORD
- VAR sin_horiz_start,BYTE, 0 ; Horizontal starting-place
- VAR sin_sinptr, BYTE ; Pointer to the sine-table
-
- VAR x_rotation, BYTE, 0 ; Rotation around the x-axis
- VAR y_rotation, BYTE, 0
- VAR z_rotation, BYTE, 0
- VAR distance, DWORD, 390000h ; Distance of the 3D-object
-
- VAR center_x, WORD, 420 ; Place of the 3D-object on screen
- VAR center_y, WORD, 80
-
- VAR sin_x, DWORD ; SIN(x_rotation)
- VAR sin_y, DWORD
- VAR sin_z, DWORD
- VAR cos_x, DWORD
- VAR cos_y, DWORD
- VAR cos_z, DWORD
-
- VAR cosz_cosy, DWORD ; cos_z * cos_y
- VAR sinz_cosy, DWORD
- VAR sinz_cosx, DWORD
- VAR cosz_sinx, DWORD
- VAR cosz_cosx, DWORD
- VAR sinz_sinx, DWORD
- VAR cosy_sinx, DWORD
- VAR cosy_cosx, DWORD
-
- VAR matrix0, DWORD ; 9 slots for the 3*3 matrix
- VAR matrix1, DWORD
- VAR matrix2, DWORD
- VAR matrix3, DWORD
- VAR matrix4, DWORD
- VAR matrix5, DWORD
- VAR matrix6, DWORD
- VAR matrix7, DWORD
- VAR matrix8, DWORD
- VAR matrix9, DWORD
-
- VAR new_x, DWORD ; Rotated x-coordinate (on screen)
- VAR new_y, DWORD
- VAR new_z, DWORD
-
- VAR fade_in_progress, BYTE ; Variables for color-fading
- VAR fade_source, WORD
-
- VAR morph_source, WORD ; Variables for ball-morphing
-
- VAR retadress, WORD ; Variables for polygon-drawing
- VAR x1, WORD
- VAR y1, WORD
- VAR x2, WORD
- VAR y2, WORD
- VAR x_increase, WORD
- VAR color, BYTE
- VAR pgon_min_y, WORD
- VAR pgon_max_y, WORD
-
- VAR worm_x1, BYTE ; Variables for the worm
- VAR worm_x2, BYTE
- VAR worm_x3, BYTE
- VAR worm_y, BYTE
- VAR worm_lenght, BYTE
-
-
- ; Code ====================================================
-
- CODESEG
- STARTUPCODE
-
-
- ; Initialize everything -----------------------------------
-
- type_message:
-
- VAR_INITIALIZE ; Initialize & allocate variables
-
- MOV AX,CS ; Make sure SREGs are correct
- MOV DS,AX
- MOV ES,AX
-
- CLD ; Just to be sure
-
- MOV AX,CS ; Calculate and store segments
- MOV codesegment,AX
- ADD AX,1001h
- MOV virtualscr,AX
- ADD AX,1001h
- MOV firestartscr,AX
-
- CALL init_palettes ; Initialize palettes
-
- MOV fade_in_progress,1 ; Fade all colors to black
- MOV fade_source,OFFSET black_palette
-
- init_fadeout:
- CALL vert_retrace ; Wait for an retrace before
- CALL fade_palette ; setting new palette
-
- CMP fade_in_progress,1
- JE init_fadeout
-
- MOV AX,13h ; Set VGA mode 13h
- INT 10h
-
- CALL get_fonts ; Get CGA & VGA fonts
-
- CALL create_sincos_table ; Create full sincos-table
-
- CALL init_virtual ; Initialize virtual screen
-
- CALL init_pgtable ; Initialize table for polygons
-
- CALL init_starfield ; Initialize starfield
-
- MOV dot_curr_char,OFFSET dot_text ; Start dot-scroll from here
-
- MOV count,30 ; Wait for the screen to settle down
-
- screen_wait:
- CALL vert_retrace
-
- DEC count
- JNZ screen_wait
-
-
- ; Part 1: Ball-vectors ------------------------------------
-
- MOV fade_in_progress,1 ; Fade in
- MOV fade_source,OFFSET palette
-
- MOV morph_source,OFFSET ball_objects + 84
-
- MOV sin_start_char,OFFSET sintext_balls ; Sinus-scroll start
-
- CALL handle_sinus ; Show sinus-scroll
-
- ball_loop:
- CALL draw_background ; Redraw backround (erase balls)
-
- CALL starfield ; Draw stars
-
- CMP morph_source,OFFSET ball_objects + 84*5
- JB ball_no_end_slide ; Is the object '95'?
-
- CMP timer,300 ; Is it time for sliding?
- JB ball_no_end_slide
-
- SUB center_x,2 ; Slide object to the left
-
- CMP center_x,-100 ; Time for the next part?
- JL part_2
-
- ball_no_end_slide:
- CMP morph_source,OFFSET ball_objects
- JB ball_no_start_slide ; Is the object 'circle'?
-
- CMP center_x,154 ; Is the object in the center of the
- JB ball_no_start_slide ; screen?
-
- SUB center_x,2 ; No -> Slide object to the left
-
- ball_no_start_slide:
- CALL morph_balls ; Morph ball-objects
-
- CALL calc_matrix ; Calculate 3D-matrix
-
- MOV SI,OFFSET ball_objects
- MOV count,28
- CALL rotate_all ; Rotate all balls
-
- MOV SI,OFFSET screen_coords
- MOV CX,28
- CALL sort_coords ; Sort balls by distance
-
- CALL draw_balls ; Draw balls & shadows
-
- CALL dot_scroll ; Update dot-scroll
-
- CALL vert_retrace ; Wait for an vertical retrace
-
- CALL flip_screen ; Show virtual screen
-
- INC x_rotation ; Rotate object
- INC y_rotation
- ADD z_rotation,2
-
- MOVZX CX,x_rotation ; Rotate some more (break the pattern)
- BT CX,7
- ADC y_rotation,0
-
- MOV AH,1 ; Check for a key
- INT 16h
- JZ ball_loop ; No key pressed -> Keep looping
-
- MOV AH,0 ; Get the keypress from buffer
- INT 16h
-
- CMP AL,27 ; ESC exits
- JE exit2dos
-
- CMP AL,' ' ; Space skips this part
- JNE ball_loop
-
-
- ; Part 2: Filled vectors ----------------------------------
-
- part_2:
- MOV center_x,160 ; Slide to left from here
-
- MOV x_rotation,215 ; Change viewpoint
- MOV y_rotation,128
-
- MOV distance,310000h ; Move object closer
-
- MOV sin_start_char,OFFSET sintext_fvectors ; Sinus-scroll start
-
- CALL handle_sinus
-
- MOV timer,0 ; Reset timer
-
- fvectors_loop:
- INC timer ; Advance timer
-
- CMP timer,100 ; Morph from dot to stick?
- JB morph_to_stick
-
- CMP timer,600 ; Morph from stick to flag?
- JB morph_to_flag
-
- CMP timer,1200 ; From flag to map?
- JB morph_to_map
-
- CMP timer,1470 ; From map to dot?
- JB morph_to_dot
-
- JMP part_3 ; Jump to the next part
-
-
- fvectors_back_here:
- CALL draw_background ; Redraw backround (erase balls)
-
- CALL starfield ; Draw starfield
-
- CALL calc_matrix ; Calculate 3D-matrix
-
- MOV SI,OFFSET vector_start
- MOV count,31
- CALL rotate_all ; Rotate all points
-
- MOV SI,OFFSET screen_coords ; Draw bottom half
- MOV count,8
- MOV color,15
- CALL draw_polygon
-
- MOV count,6 ; Draw upper half
- MOV color,15
- CALL draw_polygon
-
- MOV count,5 ; Draw 'head'
- MOV color,15
- CALL draw_polygon
-
- MOV count,4 ; Draw 'arm'
- MOV color,15
- CALL draw_polygon
-
- MOV count,4 ; Draw part of the arrow
- MOV color,95
- CALL draw_polygon
-
- MOV count,4 ; Draw part of the arrow
- MOV color,95
- CALL draw_polygon
-
-
- CALL dot_scroll ; Update dot-scroll
-
- CALL vert_retrace ; Wait for an vertical retrace
-
- CALL flip_screen ; Show virtual screen
-
- INC z_rotation ; Rotate viewpoint
-
- MOV AH,1 ; Check for a key
- INT 16h
- JZ fvectors_loop ; No key pressed -> Keep looping
-
- MOV AH,0 ; Get the keypress from buffer
- INT 16h
-
- CMP AL,27 ; ESC exits
- JE exit2dos
-
- CMP AL,' ' ; Space skips this part
- JNE fvectors_loop
-
-
- ; Part 3: Wormie ------------------------------------------
-
- part_3:
- MOV sin_start_char,OFFSET sintext_wormie ; Sinus-scroll start
-
- CALL handle_sinus ; Handle sinus-scroll
-
- MOV worm_lenght,1 ; Starting lenght
- MOV center_x,154 ; Center of the object on screen
-
- MOV timer,0 ; Reset timer
-
- wormie_loop:
- INC timer ; Advance timer
-
- CMP timer,1800 ; Time to slide to the left?
- JB wormie_maxsize
-
- SUB center_x,2 ; Yes -> Slide wormie
-
- CMP center_x,-140 ; Time for the next part?
- JL part_4
-
- wormie_maxsize:
- CMP worm_lenght,250 ; Has the worm reached it's max size?
- JE wormie_cont ; Yes -> Continue
-
- CMP power_meter,500 ; Do we have enough CPU-power?
- JB wormie_cont ; No -> Don't grow
-
- MOV AX,timer ; Does the worm need to grow?
- TEST AX,3
- JNZ wormie_cont
-
- INC worm_lenght ; Yes
-
- wormie_cont:
- CALL draw_background ; Redraw backround (erase balls)
-
- CALL starfield ; Draw stars
-
- CALL draw_wormie ; Draw worm
-
- CALL dot_scroll ; Update dot-scroll
-
- CALL vert_retrace ; Wait for an vertical retrace
-
- CALL flip_screen ; Show virtual screen
-
- MOV AH,1 ; Check for a key
- INT 16h
- JZ wormie_loop ; No key pressed -> Keep looping
-
- MOV AH,0 ; Get the keypress from buffer
- INT 16h
-
- CMP AL,27 ; ESC exits
- JE exit2dos
-
- CMP AL,' ' ; Space skips this part
- JNE wormie_loop
-
-
- ; Part 4: The End -----------------------------------------
-
- part_4:
- MOV fade_in_progress,1 ; Fade all colors to black
- MOV fade_source,OFFSET black_palette
-
- MOV count,100
-
- part4_fadeout:
- CALL dot_scroll ; Update dot-scroll
-
- CALL vert_retrace ; Wait for an retrace before
- CALL fade_palette ; setting new palette
-
- CALL flip_screen ; Show virtualscreen
-
- DEC count ; Loop
- JNZ part4_fadeout
-
- CALL handle_fire ; Show burning text
-
- JMP exit2dos_no_fade ; Exit
-
-
- ; Handle sinus-scroll -------------------------------------
-
- handle_sinus:
- CALL draw_background ; Redraw backround (erase everything)
-
- CALL starfield ; Draw starfield
-
- CALL sinus_scroll ; Update sinus-scroll
-
- CALL dot_scroll ; Update dot-scroll
-
- CALL vert_retrace ; Wait for an vertical retrace
-
- CALL fade_palette ; Fade palette (if needed)
-
- CALL flip_screen ; Show virtual screen
-
- MOV SI,sin_start_char ; Get current sinus-scroll char
- MOV AL,[SI]
-
- CMP AL,0 ; Is it 0?
- JNE _handle_sinus_cont ; No -> Keep scrollin'
-
- INC sin_start_char ; Yes -> Skip over the 0
-
- RET ; Quit
-
- _handle_sinus_cont:
- MOV AH,1 ; Check for a key
- INT 16h
- JZ handle_sinus ; No key pressed -> Keep looping
-
- MOV AH,0 ; Get the keypress from buffer
- INT 16h
-
- CMP AL,27 ; ESC exits
- JE exit2dos
-
- CMP AL,' ' ; Space skips this part
- JNE handle_sinus
-
- RET
-
-
- ; Cleanup and exit ----------------------------------------
-
- exit2dos:
-
- MOV fade_in_progress,1 ; Fade all colors to black
- MOV fade_source,OFFSET black_palette
-
- exit_fadeout:
- CALL vert_retrace ; Wait for an retrace before
- CALL fade_palette ; setting new palette
-
- CMP fade_in_progress,1
- JE exit_fadeout
-
- exit2dos_no_fade:
- MOV AX,3 ; Set normal textmode
- INT 10h
-
- MOV count,30 ; Wait for the screen to settle down
-
- exit_wait:
- CALL vert_retrace
-
- DEC count
- JNZ exit_wait
-
- MOV AX,1301h ; Print exitstring
- MOV BX,30
- MOV CX,OFFSET end_text_end - end_text
- MOV DX,0101h
- MOV BP,OFFSET end_text
- INT 10h
-
- VAR_DEALLOCATE ; Deallocate variables
-
- MOV AX,4C00h ; Exit 2 DOS
- INT 21h
-
-
- ; Initalization ===========================================
-
- ; Get CGA 8*8 & VGA 8*16 fonts ----------------------------
-
- PROC get_fonts
-
- PUSH BP
-
- MOV AX,1130h ; Get pointer to the CGA 8*8 font
- MOV BH,3
- INT 10h
-
- MOV AX,ES ; ES:BP -> DS:SI = Source adress
- MOV DS,AX
- MOV SI,BP
-
- POP BP
-
- MOV ES,codesegment ; ES:DI = Destination adress
- MOV DI,OFFSET cga_font
-
- MOV CX,512 ; Copy 512 WORDs (128 characters)
-
- REP MOVSW ; Copy font
-
- PUSH BP
-
- MOV AX,1130h ; Get pointer to the VGA 8*16 font
- MOV BH,6
- INT 10h
-
- MOV AX,ES ; ES:BP -> DS:SI = Source adress
- MOV DS,AX
- MOV SI,BP
-
- POP BP
-
- MOV ES,codesegment ; ES:DI = Destination adress
- MOV DI,OFFSET vga_font
-
- MOV CX,1024 ; Copy 128 characters
-
- REP MOVSW ; Copy font
-
- MOV DS,codesegment ; Restore regs
-
- RET
-
- ENDP
-
-
- ; Create full sincos-table --------------------------------
-
- PROC create_sincos_table
-
- MOV SI,OFFSET partial_sincos ; Copy first quadrant of the table
- MOV DI,OFFSET sincos_table
- MOV CX,65
-
- REP MOVSW
-
- MOV SI,OFFSET sincos_table + 126
-
- _create_sct_2nd:
- MOV AX,[SI] ; 2nd quadrant is the same as the
- MOV [DI],AX ; first reversed
-
- DEC SI
- DEC SI
- INC DI
- INC DI
-
- CMP SI,OFFSET sincos_table
- JA _create_sct_2nd
-
- _create_sct_3rd_4th:
- MOVSW ; 3rd & 4th quadrants are the same as
- NEG [WORD DI-2] ; the 1st & 2nd, only negative
-
- CMP SI,OFFSET sincos_table + 256
- JB _create_sct_3rd_4th
-
- RET
-
- ENDP
-
-
- ; Initialize palettes -------------------------------------
-
- PROC init_palettes
-
- CALL vert_retrace ; Must do before reading the palette
-
- MOV AX,1017h ; Read current palette
- MOV BX,0
- MOV CX,96
- MOV DX,OFFSET vga_palette
- INT 10h
-
- MOV DI,OFFSET black_palette ; Create all black palette
- XOR AX,AX ; and stuff
- MOV CX,244
-
- REP STOSW
-
- MOV DI,OFFSET palette ; Create slide of greys
- MOV CX,16 ; 16 colors
- XOR AX,AX
-
- _init_pal_grey:
- STOSW ; Store 3 bytes (RGB)
- STOSB
-
- ADD AX,0404h ; Advance RGB-values
-
- LOOP _init_pal_grey
-
- MOV SI,OFFSET colors ; Copy fixed colors
- MOV CX,24
-
- REP MOVSW
-
- MOV AL,0 ; Create slide of blues
-
- _init_pal_blue:
- MOV [WORD DI],0 ; Red & green are zeros
- MOV [DI+2],AL ; Blue
-
- INC AL ; Next blue is little lighter
- ADD DI,3 ; Increase pointer
-
- CMP DI,OFFSET palette+288 ; Done?
- JB _init_pal_blue
-
- RET
-
- ENDP
-
-
- ; Initialize palette for the fire -------------------------
-
- PROC init_fire_palette
-
- XOR AX,AX ; Create colors for the fire
- MOV BL,00
-
- MOV DI,OFFSET palette ; Starting offset of the palette
-
- MOV count,0 ; Reset counter
-
- _init_pal_fire:
- INC count ; Increase counter
-
- MOV [DI],AX ; Store RGB
- MOV [DI+2],BL
-
- ADD DI,3 ; Advance pointer
-
- CMP count,31 ; Do we have enough reds?
- JA _init_pal_fire_yellow
-
- ADD AL,2 ; No -> Increase red
-
- JMP _init_pal_fire ; Loop
-
- _init_pal_fire_yellow:
- CMP count,62 ; Do we have enough yellows?
- JA _init_pal_fire_white
-
- ADD AH,2 ; No -> Increase green
-
- JMP _init_pal_fire ; Loop
-
- _init_pal_fire_white:
- CMP count,93 ; Do we have enough whites?
- JA _init_pal_fire_end
-
- ADD BL,2 ; No -> Increase blue
-
- JMP _init_pal_fire ; Loop
-
- _init_pal_fire_end:
- MOV [DWORD DI],3F3F3F3Fh ; Store last 2 colors
- MOV [WORD DI+4],3F3Fh
-
- RET
-
- ENDP
-
-
- ; Initialize virtual screen -------------------------------
-
- PROC init_virtual
-
- CALL draw_background ; Draw background
-
- MOV ES,virtualscr ; Draw here
- MOV DI,58240 ; Starting offset
-
- XOR AX,AX ; Draw 3 black lines
- MOV CX,240
-
- REP STOSD
-
- MOV count,8 ; Dot-scroll has 8 rows
-
- _init_virt_dot:
- MOV AX,0018h ; One black and one green dot
- MOV CX,160 ; Draw one line
-
- REP STOSW
-
- XOR AX,AX ; Draw one black line
- MOV CX,160
-
- REP STOSW
-
- DEC count ; Done?
- JNZ _init_virt_dot
-
- MOV ES,codesegment ; Restore ES
-
- RET
-
- ENDP
-
-
- ; Initialize table for polygon-drawing --------------------
-
- PROC init_pgtable
-
- MOV DI,OFFSET pg_table ; Fill the table with 8000h
- MOV CX,200
- MOV AX,8000h
-
- REP STOSW
-
- RET
-
- ENDP
-
-
- ; Initialize starfield ------------------------------------
-
- PROC init_starfield
-
- MOV DI,OFFSET starfield_data ; Stardata offset
- MOV SI,100h ; Source for random numbers
- XOR BX,BX ; First star's offset
- MOV CX,100 ; Create 200 stars
-
- _init_stars_loop:
- XOR AX,AX
-
- LODSB ; Get random number
- ADD AX,270
-
- ADD BX,AX ; Advance pointer
-
- MOV AX,BX ; Store pointer
- STOSW
-
- ROR AL,4
- STOSB ; Store color
-
- LOOP _init_stars_loop
-
- RET
-
- ENDP
-
-
- ; Color routines ==========================================
-
- ; Set palette ---------------------------------------------
-
- PROC set_palette
-
- MOV DX,3C8h ; Start from color 0
- XOR AL,AL
- OUT DX,AL
-
- INC DX ; Output to port 3C9
- MOV CX,288 ; Set 288 registers (96 colors)
- MOV SI,OFFSET vga_palette ; Offset of the palette
-
- REP OUTSB ; Set DACs
-
- RET
-
- ENDP
-
-
- ; Fade palette --------------------------------------------
-
- PROC fade_palette
-
- CMP fade_in_progress,0 ; Do we have to do it?
- JE _fade_pal_end
-
- MOV SI,fade_source ; Destination palette
- MOV DI,OFFSET vga_palette ; Current palette
- MOV CX,288
- CALL morph ; Morph (fade) palette
-
- CMP AX,0 ; Are we through with the fading?
- JE _fade_pal_set
-
- MOV fade_in_progress,0 ; Yep
-
- _fade_pal_set:
- CALL set_palette ; Set new palette
-
- _fade_pal_end:
- RET
-
- ENDP
-
-
- ; Scroll routines =========================================
-
- ; Update dot-scroll on the bottom of the screen -----------
-
- PROC dot_scroll
-
- CALL dot_2left ; Scroll to the left
-
- MOV ES,virtualscr ; Scroll here
-
- DEC dot_horiz_place ; Are we through with the last char?
- JNS _dot_still_the_same
-
- INC dot_curr_char ; Yep -> Next char from the string
- MOV dot_horiz_place,7
-
- _dot_still_the_same:
- MOV SI,dot_curr_char ; Get current char
- MOVZX BX,[SI]
-
- CMP BL,0 ; Is it 0?
- JNE _dot_char_not_0 ; Nope -> Continue
-
- MOV dot_curr_char,OFFSET dot_text ; Yes -> Reset charptr
-
- _dot_char_not_0:
- SHL BX,3 ; Every char takes 8 bytes
- ADD BX,OFFSET cga_font ; BX = Ptr to the char in font
-
- MOV DI,0E87Eh ; Start drawing from here
- MOVZX DX,dot_horiz_place ; Draw this column from the char
-
- _dot_loop:
- XOR AL,AL
- BT [BX],DX ; Get one bit from the font
- ADC AL,24 ; Calculate color
- INC BX
-
- MOV [ES:DI],AL ; Draw
-
- ADD DI,640 ; Next row (2 rows down actually)
-
- CMP DI,64000 ; Loop through all rows
- JB _dot_loop
-
- MOV ES,codesegment ; Restore ES
-
- RET
-
- ENDP
-
-
- ; Scroll dot-scroll to the left ---------------------------
-
- PROC dot_2left
-
- MOV AX,virtualscr ; Adress of the video memory
- MOV DS,AX
- MOV ES,AX
-
- MOV SI,0E742h ; Copy from
- MOV DI,0E740h ; Copy to
-
- _dot_2left_loop:
- MOV CX,159 ; One line = 159 WORDs
-
- REP MOVSW ; Scroll one line
-
- ADD SI,322 ; SI & DI 2 rows down
- ADD DI,322
-
- CMP DI,64000 ; All lines scrolled?
- JB _dot_2left_loop
-
- MOV AX,CS ; Restore DS & ES
- MOV DS,AX
- MOV ES,AX
-
- RET
-
- ENDP
-
-
- ; Update sinus-scroll -------------------------------------
-
- PROC sinus_scroll
-
- MOV ES,virtualscr ; Draw here
-
- ADD sin_sinptr,4 ; Move sinus-effect
-
- DEC sin_horiz_start ; Scroll to the left
- JNS _sin_same_start_char ; Next starting char?
-
- INC sin_start_char ; Yep -> Next char from the string
- MOV sin_horiz_start,7
-
- _sin_same_start_char:
- MOV AX,sin_start_char ; Startptr to text
- MOV sin_curr_char,AX
-
- MOV AL,sin_sinptr ; Pointer to sinetable
-
- XOR BX,BX ; Starting x-coordinate
- MOVZX DI,sin_horiz_start ; Horizontal position inside char
-
- _sin_loop:
- MOVZX SI,AL ; Get SIN(angle)
- SHL SI,1 ; Table contains WORDs
- MOV DX,[WORD SI+sincos_table] ; Get sine
-
- INC AL ; Increase sine-pointer
-
- SAR DX,9 ; Calculate y-coordinate
- ADD DX,80
-
- MOV SI,sin_curr_char ; SI=Pointer to char in font
- MOVZX SI,[SI]
- SHL SI,4
- ADD SI,OFFSET vga_font
-
- MOV CX,15 ; Loop through 16 rows
-
- _sin_column_loop:
- BT [SI],DI ; Get one bit from the font
- JNC _sin_column_nodraw ; Bit was 0 -> Don't draw
-
- PUSHA
-
- ADD BH,DL ; Address = (y * 320) + x
- SHL DX,6
- ADD BX,DX
-
- MOV SI,OFFSET sinus_colors
- ADD SI,CX
-
- MOV AL,[SI]
- MOV AH,AL
-
- MOV [WORD ES:BX],AX ; Draw 2 points
-
- POPA ; Funny, but must be here!
- PUSHA
-
- SUB DX,80 ; Calculate y-coordinate for shadow
- SAR DX,2
- ADD DX,155
-
- ADD BH,DL ; Address = (y * 320) + x
- SHL DX,6
- ADD BX,DX
-
- MOV [WORD ES:BX],1A1Ah ; Draw 2 points of shadow
-
- POPA
-
- _sin_column_nodraw:
- INC DX ; Increase y-coordinate
- INC SI ; Next row in the font
-
- LOOP _sin_column_loop ; Loop through all rows
-
- DEC DI ; Next column
- JNS _sin_char_not_finished ; This char drawed?
-
- INC sin_curr_char ; Yes -> Next char
-
- MOV DI,7
-
- _sin_char_not_finished:
- ADD BX,2 ; Increase x-coordinate
-
- CMP BX,320 ; All columns drawed
- JNE _sin_loop
-
- MOV ES,codesegment
-
- RET
-
- ENDP
-
-
- ; Graphic routines ========================================
-
- ; Wait for the next vertical retrace ----------------------
-
- PROC vert_retrace
-
- MOV power_meter,0 ; Zero out our counter
-
- MOV DX,3DAh ; Use port 3D4
-
- _vert_retrace_off:
- IN AL,DX ; Get vertical retrace state
-
- TEST AL,08h
- JNZ _vert_retrace_off ; Loop until it's off
-
- _vert_retrace_on:
- INC power_meter ; Increase counter
-
- IN AL,DX ; Get vertical retrace state
-
- TEST AL,08h
- JZ _vert_retrace_on ; Loop until it's on
-
- RET
-
- ENDP
-
-
- ; Draw sprite ---------------------------------------------
-
- ; BX - Sprite number
- ; CX - X-coordinate
- ; DX - Y-coordinate
-
- PROC putsprite
-
- CMP CX,305 ; Check x-limits
- JA _ps_end
-
- MOV ES,virtualscr ; Draw to virtual screen
-
- INC BX
- SHL BX,1 ; Start of the sprite to SI
- MOV SI,[BX+OFFSET sprites]
- ADD SI,OFFSET sprites
-
- MOVZX AX,[SI] ; Get width
-
- ADD CH,DL ; Count destination adress
- SHL DX,6
- ADD CX,DX
- MOV DI,CX
-
- MOV DX,320 ; DX = 320-width
- SUB DX,AX
-
- ADD AX,DI ; End of the first line
-
- MOV BL,[SI+1] ; Height = Lines to draw
- ADD SI,2
-
- XOR CH,CH ; We need this for BYTE -> WORD
-
- _ps_loop:
- MOV CL,[SI] ; Jump over the invicible area
- ADD DI,CX
- MOV CL,[SI+1] ; Number of visible points
- ADD SI,2
-
- SHR CL,1 ; Draw using WORDs
-
- REP MOVSW ; Draw
-
- JNC _ps_even ; Still one to draw?
-
- MOVSB ; Yes -> Draw BYTE
-
- _ps_even:
- CMP DI,AX ; End of this line?
- JB _ps_loop ; No -> Keep drawing
-
- ADD AX,320 ; Yes -> Next line ends just below
- ADD DI,DX ; DI to the start of the next line
-
- DEC BL ; All of the lines drawed?
- JNZ _ps_loop ; No -> Loop
-
- MOV ES,codesegment
-
- _ps_end:
- RET
-
- ENDP
-
-
- ; Draw all balls ------------------------------------------
-
- PROC draw_balls
-
- MOV count,28 ; Number of shadows to draw
- MOV SI,OFFSET screen_coords ; Source offset
-
- _draw_balls_shadows:
- MOV CX,[SI] ; Get x
- MOV BX,[SI+4] ; Get z
- SAR BX,11 ; Place of the shadow
- MOV DX,155
- SUB DX,BX
- MOV BX,2 ; Sprite number
-
- PUSH SI
- CALL putsprite ; Draw shadow
- POP SI
-
- ADD SI,6 ; Next shadow
-
- DEC count ; Done?
- JA _draw_balls_shadows
-
- MOV count,28 ; Number of balls to draw
- MOV SI,OFFSET screen_coords ; Source offset
-
- _draw_balls_loop:
- MOV CX,[SI] ; Get x
- MOV DX,[SI+2] ; Get y
- MOV BX,[SI+4] ; Get z
- SHR BX,15 ; Big or small ball?
- XOR BX,1
-
- PUSH SI
- CALL putsprite ; Draw ball
- POP SI
-
- ADD SI,6 ; Next ball
-
- DEC count ; Done?
- JA _draw_balls_loop
-
- RET
-
- ENDP
-
-
- ; Flip virtual screen to VGA ------------------------------
-
- PROC flip_screen
-
- MOV DS,virtualscr ; Source segment
- MOV ES,vgasegment ; Destination segment
- XOR DI,DI ; Offsets
- XOR SI,SI
- MOV ECX,16000 ; Copy this many DWORDs
-
- REP MOVSD ; Copy
-
- MOV DS,codesegment ; Restore Sregs
- MOV ES,codesegment
-
- RET
-
- ENDP
-
-
- ; Redraw background ---------------------------------------
-
- PROC draw_background
-
- MOV ES,virtualscr ; Draw eveything here
- XOR DI,DI ; Starting offset
- XOR EAX,EAX ; Fill with color 0 (black)
- MOV CX,9440 ; FIll first lines
-
- REP STOSD
-
- MOV count,64 ; Create slide of blues
- MOV AX,2020h ; Starting color
-
- _init_bg_blue:
- MOV CX,160 ; Draw one line
-
- REP STOSW
-
- ADD AX,0101h ; Next color
-
- DEC count ; Done?
- JNZ _init_bg_blue
-
- MOV ES,codesegment ; Restore ES
-
- RET
-
- ENDP
-
-
- ; Plot one point ------------------------------------------
-
- ; BX - X-coordinate
- ; DX - Y-coordinate
- ; AL - Color
- ; ES - Segment to draw to
-
- PROC plot
-
- CMP BX,319 ; Check x-limits
- JA _plot_end
-
- CMP DX,199 ; Check y-limits
- JA _plot_end
-
- ADD BH,DL ; Address = (y * 320) + x
- SHL DX,6
- ADD BX,DX
-
- MOV [ES:BX],AL ; Draw
-
- _plot_end:
- RET
-
- ENDP
-
-
- ; Draw horizontal line ------------------------------------
-
- ; AL - color
- ; BX - x1
- ; CX - x2
- ; DX - y
- ; ES - Segment to draw to
-
- PROC scanline
-
- CMP DX,184 ; Y-coordinate out of range?
- JA _scanl_end ; Yes - > Quit
-
- CMP CX,BX
- JE plot ; x1 = x2 -> Plot one point
- JG _scanl_no_swap ; x1 > x2?
-
- XCHG CX,BX ; Yes -> Swap them
-
- _scanl_no_swap:
- CMP BX,0 ; x1 < 0?
- JG _scanl_x1_ok
-
- XOR BX,BX ; Yes -> x1 = 0
-
- _scanl_x1_ok:
- CMP CX,320 ; x2 > 320?
- JL _scanl_x2_ok
-
- MOV CX,320 ; Yes -> x2 = 320
-
- _scanl_x2_ok:
- CMP BX,CX ; Out of the screen horizontally?
- JG _scanl_end ; Yes -> Quit
-
- SUB CX,BX ; Calculate lenght
- INC CX
-
- ADD BH,DL ; DI=y*320+x1 (starting adress)
- SHL DX,6
- ADD BX,DX
- MOV DI,BX
-
- MOV AH,AL ; Fix color for WORD-size writes
-
- SHR CX,1 ; Draw as WORDs
-
- REP STOSW ; Draw line
-
- JNC _scanl_end ; Was the lenght even?
-
- STOSB ; No -> Draw the last pixel
-
- _scanl_end:
- RET
-
- ENDP
-
-
- ; Draw polygon --------------------------------------------
-
- ; color - Color
- ; Coordinates are pushed to stack: 8000h,X1,Y1,X2,Y2,...,Xn,Yn(,returnadress)
- ; (There _MUST_ be at least three pairs of coordinates!)
-
- PROC polygon
-
- ; This part gets the coordinates from the stack
-
- MOV ES,virtualscr ; Draw to virtual screen
-
- POP retadress ; Get returnadress
-
- MOV pgon_min_y,199 ; Initialize min/max y-coordinate
- MOV pgon_max_y,0
-
- POP DX ; Get first pair of coordinates
- POP CX
-
- CALL _pgon_check_y ; Check y for top/bottom
-
- MOV x1,CX ; Save them for the last line:
- MOV y1,DX ; (Xn, Yn) - (X1, Y1)
-
- POP y2 ; Get next pair of coords
- POP x2
-
- CALL _pgline ; Draw the line
-
- _polygon_loop:
- MOV CX,x2 ; The ending coords of the last line
- MOV DX,y2 ; are the starting coords of the next
-
- CALL _pgon_check_y ; Check y for top/bottom
-
- POP y2 ; Get next Y
- CMP y2,8000h ; End of the coords?
- JE _polygon_end ; Yes - > Quit
-
- POP x2 ; Get next X
-
- CALL _pgline ; Draw the line
-
- JMP _polygon_loop ; Loop
-
- _polygon_end:
- MOV y2,DX ; Restore DX after POP
- MOV CX,x1 ; Get saved (X1, Y1)
- MOV DX,y1
-
- CALL _pgline ; Draw the last line
-
- MOV ES,codesegment ; Restore ES
-
- MOV DI,pgon_min_y ; Clear PG_TABLE between min & max
- SHL DI,1 ; y-coordinate
- ADD DI,OFFSET pg_table
-
- MOV CX,pgon_max_y
- SUB CX,pgon_min_y
- INC CX
-
- MOV AX,8000h
-
- REP STOSW
-
- PUSH retadress ; Restore returnadress
-
- RET ; Exit
-
-
- ; This part draws the lines and fills the polygon
- ; The line is drawed between (CX, DX) and (x2, y2)
-
- _pgline:
- PUSH x2 ; Save (x2,y2)
- PUSH y2
-
- CMP DX,y2 ; Is DX = y2?
- JNE _pgl_no_horiz
-
- MOV BX,x2 ; Yes -> Draw horizontal line
-
- POP EAX ; Dump saved (x2, y2)
- MOV AL,color ; Get color
-
- JMP scanline ; Draw scanline
-
- _pgl_no_horiz:
- JL _pgl_no_swap ; Is DX > y2?
-
- XCHG x2,CX ; Yes -> Swap coordinates
- XCHG y2,DX
-
- _pgl_no_swap:
- MOV SI,DX ; Save DX (IDIV destroys DX)
-
- MOV AX,x2 ; AX = x2-x1
- SUB AX,CX
- MOV BX,y2 ; BX = y2-y1
- SUB BX,DX
-
- CWD ; Convert AX -> DX:AX for IDIV
- SHL AX,6 ; Lower 6 bits are decimals
-
- IDIV BX ; AX = (x2-x1)/(y2-y1)
-
- MOV x_increase,AX ; Save the result
-
- MOV DX,SI ; Restore DX
-
- MOV SI,CX ; Starting x-coordinate
- MOV BX,CX
- SHL SI,6 ; Lower 6 bits are decimals
-
- MOV AL,color ; Get drawing color
-
- MOV DI,DX ; Calculate index to the table
- SHL DI,1
- ADD DI,OFFSET pg_table
-
- ADD SI,20h
-
- _pgl_loop:
- MOV CX,[DI] ; Get a value from the table
-
- CMP CX,8000h ; Do we have an value in there?
- JNE _pgl_draw_scanline ; Yes -> Draw one line
-
- MOV [DI],BX ; No -> Store current x to the table
-
- JMP _pgl_next_line ; We don't wanna draw now
-
- _pgl_draw_scanline:
- PUSHA ; Save regs
-
- CALL scanline ; Draw line
-
- POPA ; Restore regs
-
- _pgl_next_line:
- ADD SI,x_increase ; Increase x-coordinate
- MOV BX,SI ; Move it to BX (BX=integer part of x)
- SAR BX,6 ; Get rid of the decimals
-
- INC DX ; Increase y-coordinate by 1
-
- ADD DI,2
-
- CMP DX,y2 ; All lines drawed?
- JLE _pgl_loop ; No -> Keep drawing
-
- POP y2 ; Restore (x2, y2)
- POP x2
-
- RET
-
-
- ; This subroutine checks if given Y is the top/bottom y-coordinate
-
- _pgon_check_y:
- CMP DX,pgon_min_y ; Y greater than top coordinate?
- JGE _pgon_check_max_y ; Yes -> Skip set
-
- MOV pgon_min_y,DX ; No -> Set new top
-
- _pgon_check_max_y:
- CMP DX,pgon_max_y ; Y less than bottom coordinate?
- JLE _pgon_check_y_end ; Yes -> Skip set
-
- MOV pgon_max_y,DX ; Set new bottom coordinate
-
- _pgon_check_y_end:
- RET
-
-
- ENDP
-
-
- ; Handle polygon-drawing ----------------------------------
-
- ; count - Number of points in polygon
- ; SI - Pointer to coordinates
- ; color - Color of the polygon
-
- PROC draw_polygon
-
- MOV temp,SI ; Save SI
-
- MOV CL,count ; Use CL as a counter
-
- PUSH 8000h ; Push coordinates to stack
-
- _draw_polygon:
- PUSH [WORD SI] ; Push x
- PUSH [WORD SI+2] ; Push y
-
- ADD SI,6 ; Advance pointer
-
- DEC CL ; Loop through all points
- JNZ _draw_polygon
-
- CALL polygon ; Draw polygon
-
- MOV SI,temp ; Restore SI
-
-
- PUSH 8000h ; Push shadow's coords to stack
-
- MOV color,26 ; Change color
-
- _draw_pgon_shadow:
- PUSH [WORD SI] ; Push x
-
- MOV BX,[SI+4] ; Get z
- SAR BX,11 ; Place of the shadow
- MOV DX,155
- SUB DX,BX
-
- PUSH DX ; Push y
-
- ADD SI,6 ; Advance pointer
-
- DEC count ; Loop through all points
- JNZ _draw_pgon_shadow
-
- MOV temp,SI ; Save SI
-
- CALL polygon ; Draw shadow
-
- MOV SI,temp ; Restore SI
-
- RET
-
- ENDP
-
-
- ; Draw starfield ------------------------------------------
-
- PROC starfield
-
- MOV SI,OFFSET starfield_data ; Source offset
- MOV CX,100 ; Draw 200 stars
- MOV ES,virtualscr ; Draw here
-
- _starf_loop:
- LODSW ; Get offset of an star
-
- MOV BX,AX
-
- ADD [BYTE SI],2 ; Change color
-
- MOVZX AX,[SI] ; Get color
- SHR AL,3 ; Divide it by 8 (0-255 -> 0-31)
-
- INC SI ; Increase source pointer
-
- CMP AL,15 ; Colors 0-15 can be drawed right away
- JBE _starf_draw
-
- MOV DL,AL ; Colors 16-31 need some processing
- MOV AL,31
- SUB AL,DL
-
- _starf_draw:
- MOV [BYTE ES:BX],AL ; Draw star
-
- LOOP _starf_loop ; Loop through all stars
-
- MOV ES,codesegment ; Restore ES
-
- RET
-
- ENDP
-
-
- ; Draw wormie ---------------------------------------------
-
- PROC draw_wormie
-
- INC worm_x1 ; Wiggle worm
- ADD worm_x2,2
- INC worm_x3
-
- INC worm_y
-
- MOV AL,worm_x1 ; Load worm_?? variables to registers
- MOV AH,worm_x2
- MOV BL,worm_x3
- MOV BH,worm_y
-
- MOV CL,worm_lenght ; Init loop-counter
- MOV count,CL
-
- _dworm_loop:
- MOVZX SI,AL ; Modify x with first sine
- SHL SI,1
- MOV CX,[WORD SI+sincos_table] ; Get SIN(AL)
-
- SAR CX,8 ; Wiggle worm
- ADD AL,2
-
- MOVZX SI,AH ; Modify x with second sine
- SHL SI,1
- MOV DI,[WORD SI+sincos_table] ; Get SIN(AH)
-
- SAR DI,9 ; Wiggle
- ADD CX,DI
- ADD AH,9
-
- MOVZX SI,BL ; Modify x with 3rd sine
- SHL SI,1
- MOV DI,[WORD SI+sincos_table] ; Get SIN(BL)
-
- SAR DI,9 ; Wiggle
- ADD CX,DI
- ADD BL,3
-
- MOVZX SI,BH ; Modify y with sine
- SHL SI,1
- MOV DX,[WORD SI+sincos_table] ; Get SIN(BH)
-
- SAR DX,8 ; Wiggle
- ADD BH,3
-
- ADD CX,center_x ; Move the worm to the center of the
- ADD DX,center_y ; screen
-
- PUSHA ; Putsprite destroys regs
-
- CALL draw_worm_dot ; Draw one dot
-
- POPA ; Restore regs
-
- DEC count ; Loop through all dots
- JNZ _dworm_loop
-
- RET
-
- ENDP
-
-
- ; Draw one dot for the wormie -----------------------------
-
- ; CX - X-coordinate
- ; DX - Y -"-
-
- PROC draw_worm_dot
-
- MOV x1,CX ; Save (x,y) for the shadow
- MOV y1,DX
-
- MOV BX,3 ; Draw sprite #3 (dot)
- CALL putsprite
-
- MOV CX,x1 ; Restore (x,y)
- MOV DX,y1
-
- SHR DX,4 ; Calculate the place of the shadow
- ADD DX,155
-
- MOV BX,2 ; Draw sprite #2 (shadow)
- CALL putsprite
-
- RET
-
- ENDP
-
-
- ; Draw burning text ---------------------------------------
-
- ; AL - Color of the text
- ; DX - Startptr to text
-
- PROC draw_burning_text
-
- MOV ES,firestartscr ; Draw here
-
- MOV BX,35216 ; Startoffset on screen
- MOV DI,7 ; Startcolumn inside font
-
- MOV color,AL ; Save original color
-
- MOV CX,timer ; Randomize
- MOV temp,CX
-
- _dbt_loop:
- MOV AL,color ; Get color
- MOV AH,AL
-
- MOV SI,DX ; SI=Pointer to char in font
- MOVZX SI,[SI]
-
- CMP SI,0 ; End of the string?
- JE _dbt_end ; Oh Yes -> Quit
-
- SHL SI,4
- ADD SI,OFFSET vga_font
-
- MOV CX,15 ; Loop through 16 rows
-
- _dbt_column_loop:
- BT [SI],DI ; Get one bit from the font
- JNC _dbt_column_nodraw ; Bit was 0 -> Don't draw
-
- MOV [WORD ES:BX],AX ; Draw 2 points
-
- _dbt_column_nodraw:
- ADD BX,320 ; Increase y-coordinate
- INC SI ; Next row in the font
-
- LOOP _dbt_column_loop ; Loop through all rows
-
- DEC DI ; Next column in font
- JNS _dbt_char_not_drawed ; This char drawed?
-
- INC DX ; Yes -> Next char
- MOV DI,7
-
- MOV AL,color ; Get original color
-
- MOV SI,temp ; Calculate random color (+/- 8)
- INC temp ; For the next character
- ADD SI,900
- MOV CL,[SI]
- AND CL,00001111b
- SUB CL,6
- ADD color,CL
-
- CMP color,96 ; Check palette limits
- JB _dbt_char_not_drawed
-
- MOV color,95
-
- _dbt_char_not_drawed:
- SUB BX,4798 ; Next column on screen
-
- JMP _dbt_loop ; Loop
-
- _dbt_end:
- MOV ES,codesegment ; Restore ES
-
- RET
-
- ENDP
-
-
- ; Light me up ---------------------------------------------
-
- PROC light_me_up
-
- MOV ES,virtualscr ; Init SREGs
- MOV DS,firestartscr
-
- MOV DI,8000 ; Starting offset
-
- _lmu_loop:
- MOVZX AX,[DI+320] ; Add together 4 surrounding points
- ADD AL,[DI+318]
- MOVZX BX,[DI+640]
- ADD BL,[DI+642]
- ADD AX,BX
-
- SHR AX,2 ; Divide sum by 4
-
- DEC AL ; Fade
- JNS _lmu_draw
-
- MOV AL,0
-
- _lmu_draw:
- MOV AH,AL ; Draw as WORDs
-
- MOV [ES:DI],AX ; Draw
- ADD DI,2
-
- CMP DI,40640 ; Done?
- JB _lmu_loop
-
- MOV AX,codesegment ; Restore SREGs
- MOV ES,AX
- MOV DS,AX
-
- RET
-
- ENDP
-
-
- ; Draw mirror for the fire --------------------------------
-
- PROC draw_mirror
-
- MOV AX,virtualscr ; Init SREGs
- MOV ES,AX
- MOV DS,AX
-
- MOV SI,8000 ; Starting offsets
- MOV DI,56000
-
- _dmirror_loop:
- MOV CX,160 ; Row has 160 WORDs
-
- _dmirror_row_loop:
- LODSW ; Get color
-
- SHR AX,1 ; Fade color
- AND AX,1111111101111111b
-
- STOSW ; Store shadow
-
- LOOP _dmirror_row_loop ; Loop through this row
-
- ADD SI,320 ; Next row
- SUB DI,640
-
- CMP SI,40640 ; Done?
- JB _dmirror_loop
-
- MOV AX,codesegment ; Restore SREGs
- MOV ES,AX
- MOV DS,AX
-
- RET
-
- ENDP
-
-
- ; Handle burning text -------------------------------------
-
- PROC handle_fire
-
- MOV ES,virtualscr ; Clear virtualscreen
- XOR DI,DI
- MOV AX,DI
- MOV CX,64010
-
- REP STOSW
-
- MOV ES,firestartscr ; Clear firestartscreen
- XOR DI,DI
- MOV CX,64010
-
- REP STOSW
-
- CALL flip_screen ; Clear VGA memory
-
- CALL init_fire_palette ; Create palette for the fire
-
- MOV fade_in_progress,1 ; Fade in
- MOV fade_source,OFFSET palette
-
- MOV timer,0 ; Reset timer
-
- _hfire_loop:
- INC timer ; Advance timer
-
- CMP timer,750 ; Time to quit?
- JA _hfire_quit
-
- MOV DX,OFFSET black_palette ; NULL string offset
-
- CMP timer,700
- JA _hfire_draw
-
- MOV DX,OFFSET burning_textstring_2 ; 2nd string offset
-
- CMP timer,375
- JA _hfire_draw
-
- MOV DX,OFFSET black_palette ; NULL string offset
-
- CMP timer,350
- JA _hfire_draw
-
- MOV DX,OFFSET burning_textstring_1 ; 1st string offset
-
- _hfire_draw:
- ADD count,12 ; Advance pointer to sinetable
-
- MOVZX BX,count ; Get SIN(count)
- SHL BX,1
- MOV AX,[WORD BX+sincos_table]
-
- SAR AX,10 ; Calculate color
- ADD AX,80
-
- CALL draw_burning_text ; Draw text
-
- CALL vert_retrace ; Wait for retrace
-
- CALL light_me_up ; Create fire
-
- CALL vert_retrace ; Wait for retrace (again!)
-
- CALL fade_palette ; Fade in (if needed)
-
- CALL draw_mirror ; Draw mirror
-
- CALL flip_screen ; Show virtualscreen
-
- MOV AX,virtualscr ; Swap virtualscr & firestartscr
- XCHG AX,firestartscr
- MOV virtualscr,AX
-
- MOV AH,1 ; Check for a key
- INT 16h
- JZ _hfire_loop ; No key pressed -> Keep looping
-
- MOV AH,0 ; Get the keypress from buffer
- INT 16h
-
- MOV timer,700 ; Quit by cheating the timer
-
- JMP _hfire_loop ; Loop
-
- _hfire_quit:
- RET
-
- ENDP
-
-
- ; 3D-routines =============================================
-
- ; Get sine & cosine for an angle --------------------------
-
- ; AL - Angle (0 - 255)
-
- ; Returns:
-
- ; ECX - SIN(angle)
- ; EDX - COS(angle)
-
- PROC get_one_sincos
-
- MOVZX BX,AL ; Get SIN(angle)
-
- SHL BX,1 ; Table contains WORDs
-
- MOVSX ECX,[WORD BX+sincos_table] ; Get sine
-
- MOV BX,64 ; Get COS(angle)
- SUB BL,AL ; = SIN(64 - angle)
-
- SHL BX,1
-
- MOVSX EDX,[WORD BX+sincos_table]
-
- RET
-
- ENDP
-
-
- ; Get all sines & cosines needed --------------------------
-
- PROC get_sincos
-
- MOV AL,x_rotation ; Get sine & cosine of x_rotation
-
- CALL get_one_sincos
-
- MOV sin_x,ECX
- MOV cos_x,EDX
-
- MOV AL,y_rotation ; y_rotation
-
- CALL get_one_sincos
-
- MOV sin_y,ECX
- MOV cos_y,EDX
-
- MOV AL,z_rotation ; z_rotation
-
- CALL get_one_sincos
-
- MOV sin_z,ECX
- MOV cos_z,EDX
-
- RET
-
- ENDP
-
-
- ; Calculate matrix ----------------------------------------
-
- ; x/y/z_rotation - Angles of rotation
-
- PROC calc_matrix
-
- CALL get_sincos ; Get sines & cosines
-
- MOV EAX,cos_z ; cos_z * cos_y
- IMUL EAX,cos_y
- SAR EAX,14
- MOV cosz_cosy,EAX
-
- MOV EAX,sin_z ; sin_z * cos_y
- IMUL EAX,cos_y
- SAR EAX,14
- MOV sinz_cosy,EAX
-
- MOV EAX,sin_z ; sin_z * cos_x
- IMUL EAX,cos_x
- SAR EAX,14
- MOV sinz_cosx,EAX
-
- MOV EAX,cos_z ; cos_z * sin_x
- IMUL EAX,sin_x
- SAR EAX,14
- MOV cosz_sinx,EAX
-
- MOV EAX,cos_z ; cos_z * cos_x
- IMUL EAX,cos_x
- SAR EAX,14
- MOV cosz_cosx,EAX
-
- MOV EAX,sin_z ; sin_z * sin_x
- IMUL EAX,sin_x
- SAR EAX,14
- MOV sinz_sinx,EAX
-
- MOV EAX,cos_y ; cos_y * sin_x
- IMUL EAX,sin_x
- SAR EAX,14
- MOV cosy_sinx,EAX
-
- MOV EAX,cos_y ; cos_y * cos_x
- IMUL EAX,cos_x
- SAR EAX,14
- MOV cosy_cosx,EAX
-
- MOV EAX,cosz_cosy ; matrix0 = cos_z * cos_y
- MOV matrix0,EAX
-
- MOV EAX,sinz_cosy ; matrix1 = -sin_z * cos_y
- NEG EAX
- MOV matrix1,EAX
-
- MOV EAX,sin_y ; matrix2 = sin_y
- MOV matrix2,EAX
-
- MOV EAX,cosz_sinx ; matrix3 = sin_z * cos_x +
- IMUL EAX,sin_y ; cos_z * sin_x * sin_y
- SAR EAX,14
- ADD EAX,sinz_cosx
- MOV matrix3,EAX
-
- MOV EAX,sinz_sinx ; matrix4 = cos_z * cos_x -
- IMUL EAX,sin_y ; sin_z * sin_x * sin_y
- SAR EAX,14
- NEG EAX
- ADD EAX,cosz_cosx
- MOV matrix4,EAX
-
- MOV EAX,cosy_sinx ; matrix5 = -cos_y * sin_x
- NEG EAX
- MOV matrix5,EAX
-
- MOV EAX,cosz_cosx ; matrix6 = sin_z * sin_x -
- IMUL EAX,sin_y ; cos_z * cos_x * sin_y
- SAR EAX,14
- NEG EAX
- ADD EAX,sinz_sinx
- MOV matrix6,EAX
-
- MOV EAX,sinz_cosx ; matrix7 = cos_z * sin_x +
- IMUL EAX,sin_y ; sin_z * cos_x * sin_y
- SAR EAX,14
- ADD EAX,cosz_sinx
- MOV matrix7,EAX
-
- MOV EAX,cosy_cosx ; matrix8 = cos_y * cos_x
- MOV matrix8,EAX
-
- RET
-
- ENDP
-
-
- ; Rotate one point ----------------------------------------
-
- ; Matrix _MUST_ be calculated first using correct x/y/z_rotation values
-
- ; SI - Pointer to 3 BYTEs (x, y, z)
- ; distance - Distance of the point
- ; DI - Pointer to 3 WORDs (rotated x, y, z)
-
- ; Returns:
-
- ; New coordinates pointed by DI (3 WORDs)
-
- PROC rotate_point
-
- MOVSX EBX,[BYTE SI] ; Move x to EBX
-
- MOVSX ECX,[BYTE SI+1] ; Move y to ECX
-
- MOVSX EDX,[BYTE SI+2] ; Move z to EDX
-
- MOV EAX,EBX ; Rotate x-coordinate
- IMUL EAX,matrix0
- MOV new_x,EAX
-
- MOV EAX,ECX
- IMUL EAX,matrix1
- ADD new_x,EAX
-
- MOV EAX,EDX
- IMUL EAX,matrix2
- ADD new_x,EAX
-
- MOV EAX,EBX ; Rotate y-coordinate
- IMUL EAX,matrix3
- MOV new_y,EAX
-
- MOV EAX,ECX
- IMUL EAX,matrix4
- ADD new_y,EAX
-
- MOV EAX,EDX
- IMUL EAX,matrix5
- ADD new_y,EAX
-
- IMUL EBX,matrix6 ; Rotate z-coordinate
- MOV new_z,EBX
-
- IMUL ECX,matrix7
- ADD new_z,ECX
-
- IMUL EDX,matrix8
- ADD new_z,EDX
-
- MOV ECX,new_z ; Calculate perspective
- ADD ECX,distance
- SAR ECX,8
-
- MOV EDX,new_x ; X-coordinate
- MOV AX,DX
- SAR EDX,16
- IDIV CX
- ADD AX,center_x
- STOSW ; Store new x
-
- ADD ECX,3000 ; Stretch object horizontally
-
- MOV EDX,new_y ; Y-coordinate
- MOV AX,DX
- SAR EDX,16
- IDIV CX
- ADD AX,center_y
- STOSW ; Store new y
-
- MOV EAX,new_z
- SAR EAX,6
- STOSW ; Store new z
-
- RET
-
- ENDP
-
-
- ; Rotate all points ---------------------------------------
-
- ; Matrix _MUST_ be calculated first using correct x/y/z_rotation values
-
- ; SI - Pointer to coordinates
- ; count - Number of points to rotate
-
- PROC rotate_all
-
- MOV DI,OFFSET screen_coords ; Destination offset
-
- _rot_all_loop:
- CALL rotate_point ; Rotate one point
-
- ADD SI,3 ; Next point
-
- DEC count ; All gone?
- JA _rot_all_loop
-
- RET
-
- ENDP
-
-
- ; Sort coordinates by distance ----------------------------
-
- ; SI - Pointer to coordinates
- ; CX - Number of coordinates to sort
-
- PROC sort_coords
-
- MOV BX,SI ; Save starting adress
-
- DEC CX ; Calculate ending adress
- IMUL CX,6
- ADD CX,SI
-
- _sort_begin:
- MOV AX,[SI+4] ; Get z-coordinate
- CMP AX,[SI+10] ; Compare to next z-coordinate
- JGE _sort_no_swap ; Greater already -> no swapping
-
- MOV EAX,[SI] ; Swap x & y
- XCHG EAX,[SI+6]
- MOV [SI],EAX
- MOV AX,[SI+4] ; Swap z
- XCHG AX,[SI+10]
- MOV [SI+4],AX
-
- MOV SI,BX ; Start from the beginning again
- JMP _sort_begin ; Loop
-
- _sort_no_swap:
- ADD SI,6 ; Compare next points
-
- CMP SI,CX ; Done?
- JB _sort_begin
-
- RET
-
- ENDP
-
-
- ; Morph routines ==========================================
-
- ; Morph any array -----------------------------------------
-
- ; SI - Offset of the original array
- ; DI - Offset of the morphed array
- ; CX - Lenght of the array in BYTEs
-
- ; Returns:
-
- ; AX - 1=Morph complete
-
- PROC morph
-
- MOV AX,1 ; Assume morph is complete
-
- _morph_loop:
- MOV BL,[SI]
- CMP BL,[DI] ; Which way to go?
- JG _morph_inc ; Increase destination
- JL _morph_dec ; Decrease
-
- _morph_loop2:
- INC SI ; Increase pointers
- INC DI
-
- LOOP _morph_loop ; Done?
-
- RET ; Yep
-
- _morph_inc:
- INC [BYTE DI] ; Increase destination
- MOV AX,0 ; Morph is not complete
- JMP _morph_loop2
-
- _morph_dec:
- DEC [BYTE DI] ; Decrease destination
- MOV AX,0
- JMP _morph_loop2
-
- ENDP
-
-
- ; Morph ball-objects --------------------------------------
-
- PROC morph_balls
-
- INC timer ; Increase timer
-
- CMP timer,400 ; Do we have to morph?
- JB _morph_balls_end ; No -> Quit
-
- MOV SI,morph_source ; Object to morph to
- MOV DI,OFFSET ball_objects ; Current object
- MOV CX,84
- CALL morph ; Morph object
-
- CMP AX,0 ; Are we through with the morphing?
- JE _morph_balls_end ; No -> Quit
-
- MOV timer,0 ; Yep -> Init counter
- ADD morph_source,84 ; Next object
-
- _morph_balls_end:
- RET
-
-
- ENDP
-
-
- ; Morph from dot to stick ---------------------------------
-
- PROC morph_to_stick
-
- MOV SI,OFFSET on_my_way_to_flag
-
- JMP morph_fvectors
-
- ENDP
-
-
- ; Morph from stick to flag --------------------------------
-
- PROC morph_to_flag
-
- MOV SI,OFFSET flag_of_finland
-
- JMP morph_fvectors
-
- ENDP
-
-
- ; Morph from flag to map ----------------------------------
-
- PROC morph_to_map
-
- MOV SI,OFFSET map_of_finland
-
- JMP morph_fvectors
-
- ENDP
-
-
- ; Morph from map to dot -----------------------------------
-
- PROC morph_to_dot
-
- MOV SI,OFFSET vector_end
-
- ENDP
-
-
- ; Morph filled vectors ------------------------------------
-
- PROC morph_fvectors
-
- TEST timer,3 ; Slow down morphing
- JNZ _morph_fv_end
-
- MOV DI,OFFSET vector_start ; Morph destination
- MOV CX,93 ; Lenght of data
-
- CALL morph ; Morph object
-
- _morph_fv_end:
- JMP fvectors_back_here
-
- ENDP
-
-
- ; Data ====================================================
-
- DATASEG
-
- ; Partial palette
-
- colors:
- DB 17,00,00,26,00,00,35,00,00,44,00,00
- DB 53,00,00,63,00,00,63,32,32,63,51,51
- DB 00,20,00,31,63,31,00,00,15,63,15,15
- DB 27,27,12,39,39,12,52,52,07,63,63,00
-
-
- ; Texts for the dot-scroll
-
- dot_text:
-
- ; DB " Welcome to ""Smooth Motion"", an 4Kb-Intro released at ASSEMBLY '95. "
- ; DB "Since no credits were allowed, we'd like to quote "
- ; DB "the legendary Mr. J. Morrison: "
- ; DB "......show me the way to the next whiskey bar, "
- ; DB "but Oh, don't ask why...... "
- ; DB "Sorry, running out of space, must loop now...... "
-
-
- DB " Welcome to ""Smooth Motion"", an 4Kb-Intro released at ASSEMBLY '95. "
- DB "This incredible (!) intro is a PULP production...... "
- DB "Credits: "
- DB "** Kimmy - Design, Coding, GFX ** "
- DB "** Mr. Pink - GFX, Ideas ** "
- DB "** Mr. Purple - GFX ** "
- DB "** Dabsa - Hardware ** "
- DB "Sorry, running out of space, must loop now...... "
-
- DB 0
-
-
- ; Sinus-scroll stuff
-
- sintext_balls:
- DB " WELCOME TO THE ASSEMBLY '95 4Kb-INTRO COMPETITION. "
- DB "LET'S START WITH SOME VECTORBALLS...... ", 0
-
- sintext_fvectors:
- DB " NEXT: A DEDICATION TO KING MARA...... ", 0
-
- sintext_wormie:
- DB " STILL MORE TO COME ??? SURE, A COOL WORMIE...... ", 0
- DB " "
-
- sinus_colors:
- DB 31, 31, 31, 30, 30, 29, 28, 13, 60, 70, 80, 90, 95, 95, 95, 95
-
-
- ; Endmessages
-
- burning_textstring_1:
- DB 7, "THAT'S", 7, "ALL", 7, "FOLKS", 7, 0
-
- burning_textstring_2:
- ; DB 7, "HOPE", 7, "YA", 7, "LIKED", 7, "IT", 7, 0
-
- DB 7, "PULP", 7, 7, "PRODUCTION", 7, 0
-
-
-
- ; DB 1
- end_text:
- ; DB "──┼─┼┼╢ Smooth Motion (VOTE US!) ╟┼┼─┼──", 10, 10, 13
-
- DB "──┼─┼┼╢ Smooth Motion by PULP ╟┼┼─┼──", 10, 10, 13
-
- end_text_end:
-
-
- ; First quadrant of the sincos-table
-
- partial_sincos:
- DW 0, 402, 804, 1205, 1606, 2006, 2404, 2801
- DW 3196, 3590, 3981, 4370, 4756, 5139, 5520, 5897
- DW 6270, 6639, 7005, 7366, 7723, 8076, 8423, 8765
- DW 9102, 9434, 9760, 10080, 10394, 10702, 11003, 11297
- DW 11585, 11866, 12140, 12406, 12665, 12916, 13160, 13395
- DW 13623, 13842, 14053, 14256, 14449, 14635, 14811, 14978
- DW 15137, 15286, 15426, 15557, 15679, 15791, 15893, 15986
- DW 16069, 16143, 16207, 16261, 16305, 16340, 16364, 16379
- DW 16383
-
-
- ; Vectorball-objects (28 balls each)
-
- ball_objects:
-
- ; Circle
- DB -50, 0, 0, -42, 30, 0, -16, 48, 0, 16, 48, 0, 42, 30, 0
- DB 50, 0, 0, 42, -30, 0, 16, -48, 0, -16, -48, 0, -42, -30, 0
-
- DB -50, 0, 0, -42, 30, 0, -16, 48, 0, 16, 48, 0, 42, 30, 0
- DB 50, 0, 0, 42, -30, 0, 16, -48, 0, -16, -48, 0, -42, -30, 0
- DB -50, 0, 0, -42, 30, 0, -16, 48, 0, 16, 48, 0, 42, 30, 0
- DB 50, 0, 0, 42, -30, 0, 16, -48, 0
-
-
- ; Flat
- DB -50, -50, 0, -25, -50, 0, 0, -50, 0, 25, -50, 0, 50, -50, 0
- DB -50, -25, 0, -25, -25, 0, 0, -25, 0, 25, -25, 0, 50, -25, 0
- DB -50, 0, 0, -25, 0, 0, 25, 0, 0, 50, 0, 0
- DB -50, 25, 0, -25, 25, 0, 0, 25, 0, 25, 25, 0, 50, 25, 0
- DB -50, 50, 0, -25, 50, 0, 0, 50, 0, 25, 50, 0, 50, 50, 0
-
- DB -50, -50, 0, -25, -50, 0, 0, -50, 0, 25, -50, 0
-
- ; Box
- DB -40, 40, 40, -15, 40, 40, 15, 40, 40, 40, 40, 40
- DB -40, -40, 40, -15, -40, 40, 15, -40, 40, 40, -40, 40
- DB -40, 40, -40, -15, 40, -40, 15, 40, -40, 40, 40, -40
- DB -40, -40, -40, -15, -40, -40, 15, -40, -40, 40, -40, -40
- DB -40, 40, 15, -40, 40, -15, 40, 40, 15, 40, 40, -15
- DB -40, -40, 15, -40, -40, -15, 40, -40, 15, 40, -40, -15
- DB 15, 0, 15, -15, 0, 15, 15, 0, -15, -15, 0, -15
-
- ; Asm
- DB -50, 30, 0, -40, 30, 0
- DB -60, 20, 0, -30, 20, 0, 0, 20, 0, 10, 20, 0, 36, 20, 0, 53, 20, 0
- DB -60, 10, 0, -30, 10, 0, -12, 10, 0, 0, 5, 0, 30, 10, 0, 45, 10, 0, 60, 10, 0
- DB -60, 0, 0, -50, 0, 0, -40, 0, 0, -30, 0, 0, 10, -2, 0, 30, 0, 0, 60, 0, 0
- DB -60, -10, 0, -30, -10, 0, -10, -10, 0, 0, -10, 0, 30, -10, 0, 60, -10, 0
-
- ; 95
- DB -40, 30, 0, -30, 30, 0, 10, 30, 0, 20, 30, 0, 30, 30, 0, 40, 30, 0
- DB -50, 20, 0, -20, 20, 0, 10, 20, 0
- DB -50, 10, 0, -20, 10, 0, 10, 10, 0, 20, 10, 0, 30, 10, 0
- DB -40, 0, 0, -30, 0, 0, -20, 0, 0, 40, 0, 0
- DB -20, -10, 0, 40, -10, 0
- DB -50, -20, 0, -20, -20, 0, 10, -20, 0, 40, -20, 0
- DB -40, -30, 0, -30, -30, 0, 20, -30, 0, 30, -30, 0
-
-
- ; Vector-objects
-
- on_my_way_to_flag:
- DB 0, 0, 0, 0, 0, 0, 0, -25, 0, 0, -25, 0
- DB 0, -25, 0, 0, -25, 0, 0, 0, 0, 0, 0, 0
-
- DB 0, 0, 0, 0, 0, 0, 0, 25, 0, 0, 25, 0, 0, 25, 0, 0, 0, 0
-
- DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-
- DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-
- DB 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-
- DB 0, -25, 0, 0, 25, 0, 0, 25, 0, 0, -25, 0
-
- flag_of_finland:
- DB 32, 0, 0, 32, 0, 0, 32, -50, 0, 32, -50, 0
- DB -32, -50, 0, -32, -50, 0, -32, 0, 0, -32, 0, 0
-
- DB -32, 0, 0, -32, 0, 0, -32, 50, 0
- DB 32, 50, 0, 32, 50, 0, 32, 0, 0
-
- DB 0, 40, 0, 0, 50, 0, 32, 50, 0, 32, 50, 0, 32, 40, 0
-
- DB -32, 40, 0, -32, 50, 0, -5, 50, 0, -5, 40, 0
-
- DB -33, -25, 0, -33, -10, 0, 33, -10, 0, 33, -25, 0
-
- DB -8, -51, 0, -8, 51, 0, 8, 51, 0, 8, -51, 0
-
- map_of_finland:
- DB 17, 0, 0, 26, -24, 0, 20, -40, 0, 8, -52, 0
- DB -15, -58, 0, -28, -47, 0, -25, -22, 0, -5, 3, 0
-
- DB -5, 3, 0, -11, 16, 0, -12, 44, 0
- DB 10, 42, 0, 15, 30, 0, 17, 0, 0
-
- DB -4, 41, 0, 2, 55, 0, 8, 60, 0, 13, 55, 0, 10, 42, 0
-
- DB -22, 47, 0, -20, 52, 0, -9, 42, 0, -10, 35, 0
-
- DB -7, -55, 0, -16, -47, 0, -7, -47, 0, 2, -47, 0
- DB -10, -48, 0, -10, -30, 0, -4, -30, 0, -4, -48, 0
-
-
- ; Sprites (ball, smaller ball, shadow & worm-dot)
-
- sprites:
- DB 004,000,010,000,169,000,047,001,097,001,013,011,003,007,016,017
- DB 017,017,017,017,016,003,000,001,011,016,018,018,019,019,019,019
- DB 019,017,017,016,001,000,001,011,018,019,021,021,021,021,020,020
- DB 019,018,017,001,000,000,013,018,019,021,022,023,022,021,021,020
- DB 019,019,018,017,000,013,018,019,021,023,023,023,021,021,020,020
- DB 019,018,017,000,013,018,019,021,022,023,022,021,021,020,020,019
- DB 018,017,000,013,018,019,020,021,021,021,021,020,020,019,019,018
- DB 017,000,013,018,019,019,020,020,020,020,020,019,019,018,018,017
- DB 001,011,017,019,019,019,019,019,019,018,018,018,017,001,000,001
- DB 011,016,017,017,018,018,018,018,018,017,017,016,001,000,003,007
- DB 016,017,017,017,017,017,016,003,000,012,010,003,006,016,017,017
- DB 017,017,016,003,000,001,010,016,018,018,018,018,018,018,017,017
- DB 016,001,000,001,010,018,019,021,021,021,020,019,018,018,017,001
- DB 000,000,012,016,019,021,021,022,021,021,020,019,018,017,016,000
- DB 012,018,019,021,022,022,022,021,020,019,018,018,017,000,012,018
- DB 019,021,021,022,021,021,020,019,018,018,017,000,012,016,019,019
- DB 021,021,021,020,020,019,018,017,016,001,010,017,018,019,020,020
- DB 019,019,018,018,017,001,000,001,010,016,017,017,018,018,018,018
- DB 017,017,016,001,000,003,006,016,017,017,017,017,016,003,000,011
- DB 004,002,007,026,026,026,026,026,026,026,002,000,000,011,026,026
- DB 026,026,026,026,026,026,026,026,026,000,011,026,026,026,026,026
- DB 026,026,026,026,026,026,002,007,026,026,026,026,026,026,026,002
- DB 000,013,010,004,005,023,023,023,023,023,004,000,002,009,023,023
- DB 022,022,022,022,022,022,021,002,000,001,011,023,022,022,022,027
- DB 027,027,021,021,021,020,001,000,001,011,023,022,027,027,027,027
- DB 027,027,021,021,020,001,000,000,013,023,022,022,027,027,027,027
- DB 027,027,021,020,020,019,000,013,023,022,027,027,027,027,027,027
- DB 021,021,020,019,019,001,011,022,021,021,027,027,021,021,021,020
- DB 020,019,001,000,001,011,022,021,021,021,021,021,020,020,020,019
- DB 019,001,000,002,009,021,020,020,020,020,020,019,019,019,002,000
- DB 004,005,019,019,019,019,019,004,000
-
-
- ; Undefined data ==========================================
-
- UDATASEG
-
- vga_palette:
- DB 288 DUP (?) ; Space for palettes (96 colors each)
-
- palette:
- DB 288 DUP (?)
-
- black_palette:
- DB 288 DUP (?)
-
- vector_start:
- DB 100 DUP (?) ; First fvector-object
-
- vector_end:
- DB 100 DUP (?) ; Last fvector-object
-
- cga_font:
- DB 1024 DUP (?) ; Space for the CGA 8*8 font
-
- vga_font:
- DB 2048 DUP (?) ; Space for the VGA 8*14 font
-
- sincos_table:
- DW 256 DUP (?) ; Space for the full sincos-table
-
- screen_coords:
- DW 100 DUP (?) ; Space for the screen coordinates
-
- pg_table:
- DW 400 DUP (?) ; Table for polygon-drawing
-
- starfield_data:
- DB 300 DUP (?) ; Space for stars
-
- END
-
-
- That's all folks...
-
- Elvis lives!
-